package com.iflytek.elpmobile.utils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;

import com.simple.elpmobile.onlinecase.ThisApplication;

import android.util.Log;

/**
 * 日志输出工具类 可配置-编译配置或配置文件配置
 * 
 * @author Tiny
 * @version [版本号, 2012-4-6]
 */
public final class Logger
{

    /**
     * 无Log版本，发布前修改
     */
    public static final byte LOG_NULL = -1;

    /**
     * 只控制台输入Log
     */
    public static final byte LOG_CONSOLE = 0;

    /**
     * 只输出Log文件
     */
    public static final byte LOG_FILE = 1;

    /**
     * 控制台打印Log + 输出Log文件
     */
    public static final byte LOG_BOTH = 2;

    /**
     * TAG
     */
    private static final String TAG = "Logger";

    /**
     * 日志文件
     */
    private static final String LOG_PATH = ThisApplication.APP_PATH + 
    		File.separator + "smartlearning.log";

    /**
     * 日志文件配置开关
     */
    private static final String LOG_SWITCH = ThisApplication.APP_PATH
    		+ File.separator + "log_switch.config";

    /**
     * 日志文件最大空间，2M
     */
    private static final int LOG_MAX_SIZE = 2 * 1024 * 1024;

    /**
     * Log类型--debug
     */
    private static final byte TAG_DEBUG = 1;

    /**
     * Log类型--info
     */
    private static final byte TAG_INFO = 2;

    /**
     * Log类型--verbose
     */
    private static final byte TAG_VERBOSE = 3;

    /**
     * Log类型--warn
     */
    private static final byte TAG_WARN = 4;

    /**
     * Log类型--error
     */
    private static final byte TAG_ERROR = 5;

    /**
     * 预设的Log类型
     */
    private static byte mLogType = LOG_CONSOLE;

    /**
     * 日志文件输出流
     */
    private static FileOutputStream fos = null;

    /**
     * 文件控制日志开关
     */
    private static boolean fileSwitch = false;

    static
    {
        // 从配置文件中读取配置
        final File file = new File(LOG_SWITCH);
        if (file != null && file.exists())
        {
            mLogType = LOG_CONSOLE;
            fileSwitch = true;
            FileReader fReader = null;
            BufferedReader bReader = null;
            try
            {
                fReader = new FileReader(file);
                bReader = new BufferedReader(fReader);

                final byte type = Byte.parseByte(bReader.readLine());
                if (type <= LOG_BOTH || type >= LOG_NULL)
                {
                    mLogType = type;
                }
            }
            catch (Exception e)
            {
                // nothing to do
                Log.w(TAG, "exception=" + e.getMessage());
            }
            finally
            {
                if (bReader != null)
                {
                    try
                    {
                        bReader.close();
                        bReader = null;
                    }
                    catch (Exception e)
                    {
                        // nothing to do
                        Log.w(TAG, "exception=" + e.getMessage());
                    }
                }
                if (fReader != null)
                {
                    try
                    {
                        fReader.close();
                        fReader = null;
                    }
                    catch (Exception e)
                    {
                        // nothing to do
                        Log.w(TAG, "exception=" + e.getMessage());
                    }
                }
            }
        }
    }

    /**
     * 私有构造方法
     */
    private Logger()
    {

    }

    /**
     * 设置Log类型
     * 
     * @param type Log类型
     */
    public static void setLogType(byte type)
    {
        // 开关文件不存在，则设置日志类型
        if (!fileSwitch)
        {
            mLogType = type;
        }
    }

    /**
     * 返回Log类型
     * 
     * @return Log类型
     */
    public static byte getLogType()
    {
        return mLogType;
    }

    /**
     * Send a DEBUG log message.
     * 
     * @param tag Used to identify the source of a log message. It usually
     *            identifies the class or activity where the log call occurs.
     * @param msg The message you would like logged.
     */
    public static void d(final String tag, final String msg)
    {
        log(tag, msg, TAG_DEBUG, mLogType);
    }

    /**
     * Send a INFO log message.
     * 
     * @param tag Used to identify the source of a log message. It usually
     *            identifies the class or activity where the log call occurs.
     * @param msg The message you would like logged.
     */
    public static void i(final String tag, final String msg)
    {
        log(tag, msg, TAG_INFO, mLogType);
    }

    /**
     * Send a VERBOSE log message.
     * 
     * @param tag Used to identify the source of a log message. It usually
     *            identifies the class or activity where the log call occurs.
     * @param msg The message you would like logged.
     */
    public static void v(final String tag, final String msg)
    {
        log(tag, msg, TAG_VERBOSE, mLogType);
    }

    /**
     * Send a WARN log message.
     * 
     * @param tag Used to identify the source of a log message. It usually
     *            identifies the class or activity where the log call occurs.
     * @param msg The message you would like logged.
     */
    public static void w(final String tag, final String msg)
    {
        log(tag, msg, TAG_WARN, mLogType);
    }

    /**
     * Send a ERROR log message.
     * 
     * @param tag Used to identify the source of a log message. It usually
     *            identifies the class or activity where the log call occurs.
     * @param msg The message you would like logged.
     */
    public static void e(final String tag, final String msg)
    {
        log(tag, msg, TAG_ERROR, mLogType);
    }

    /**
     * Send a log message.
     * 
     * @param tag Used to identify the source of a log message. It usually
     *            identifies the class or activity where the log call occurs.
     * @param msg The message you would like logged.
     * @param tagType tag type.
     * @param logType log type.
     */
    private static void log(final String tag, final String msg,
            final byte tagType, final byte logType)
    {
        switch (logType)
        {
            case LOG_NULL:
                // nothing to do
                break;
            case LOG_CONSOLE:
            case LOG_BOTH:
                log(tag, msg, tagType);
                if (logType == LOG_BOTH)
                {
                    writeLog(tag, msg);
                }
                break;
            case LOG_FILE:
                writeLog(tag, msg);
                break;
            default:
                break;
        }
    }

    /**
     * Send a log message.
     * 
     * @param tag Used to identify the source of a log message. It usually
     *            identifies the class or activity where the log call occurs.
     * @param msg The message you would like logged.
     * @param tagType tag type.
     */
    private static void log(final String tag, final String msg,
            final byte tagType)
    {
        switch (tagType)
        {
            case TAG_DEBUG:
                Log.d(tag, msg);
                break;
            case TAG_INFO:
                Log.i(tag, msg);
                break;
            case TAG_VERBOSE:
                Log.v(tag, msg);
                break;
            case TAG_WARN:
                Log.w(tag, msg);
                break;
            case TAG_ERROR:
                Log.e(tag, msg);
                break;
            default:
                break;
        }
    }

    /**
     * log日志写入文件.
     * 
     * @param tag Used to identify the source of a log message. It usually
     *            identifies the class or activity where the log call occurs.
     * @param msg The message you would like logged.
     */
    private static void writeLog(final String tag, final String msg)
    {
        try
        {
            if (fos == null)
            {
                final File file = new File(LOG_PATH);
                if (file != null)
                {
                    if (file.exists())
                    {
                        if (file.length() >= LOG_MAX_SIZE)
                        {
                            file.delete();
                            file.createNewFile();
                        }
                    }
                    else
                    {
                        file.createNewFile();
                    }
                }
                fos = new FileOutputStream(file, true);
            }
            final String data = TimeFormatter.nowTime(TimeFormatter.TIME_ACCURATE)
                    + ":\t" + tag + "\t" + msg + "\n";
            fos.write(data.getBytes(), 0, data.getBytes().length);
        }
        catch (Exception e)
        {
            // nothing to do
            Log.w(TAG, e.getMessage());
        }

    }

}
